package com.yic.module.device.service.inspectionPlan;

import cn.hutool.core.collection.CollectionUtil;
import com.yic.framework.common.pojo.PageResult;
import com.yic.module.device.controller.admin.inspectionPlan.vo.InspectionPlanCreateReqVO;
import com.yic.module.device.controller.admin.inspectionPlan.vo.InspectionPlanExportReqVO;
import com.yic.module.device.controller.admin.inspectionPlan.vo.InspectionPlanPageReqVO;
import com.yic.module.device.controller.admin.inspectionPlan.vo.InspectionPlanUpdateReqVO;
import com.yic.module.device.controller.admin.inspectionPlanJob.vo.InspectionPlanJobExportReqVO;
import com.yic.module.device.controller.admin.inspectionPlanMessage.vo.InspectionPlanMessageCreateReqVO;
import com.yic.module.device.convert.inspectionPlan.InspectionPlanConvert;
import com.yic.module.device.dal.dataobject.inspectionPlan.InspectionPlanDO;
import com.yic.module.device.dal.dataobject.inspectionPlanJob.InspectionPlanJobDO;
import com.yic.module.device.dal.mysql.inspectionPlan.InspectionPlanMapper;
import com.yic.module.device.enums.inspectionPlanDevice.CommonStatusEnum;
import com.yic.module.device.enums.inspectionPlanDevice.MessageStatusEnum;
import com.yic.module.device.service.inspectionPlanDevice.InspectionPlanDeviceService;
import com.yic.module.device.service.inspectionPlanJob.InspectionPlanJobService;
import com.yic.module.device.service.inspectionPlanMessage.InspectionPlanMessageService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;

import static com.yic.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yic.module.device.enums.ErrorCodeConstants.*;

/**
 * 巡检计划 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class InspectionPlanServiceImpl implements InspectionPlanService {

    @Resource
    private InspectionPlanMapper inspectionPlanMapper;
    @Resource
    private InspectionPlanDeviceService inspectionPlanDeviceService;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private InspectionPlanMessageService inspectionPlanMessageService;
    @Resource
    @Lazy // 循环依赖，避免报错
    private InspectionPlanJobService inspectionPlanJobService;

    @Override
    public Long createInspectionPlan(InspectionPlanCreateReqVO createReqVO) {
        // 插入
        InspectionPlanDO inspectionPlan = InspectionPlanConvert.INSTANCE.convert(createReqVO);
        transactionTemplate.execute(status -> {
            inspectionPlanMapper.insert(inspectionPlan);
            inspectionPlanDeviceService.createPlanDevice(inspectionPlan.getId(),createReqVO.getDeviceList());
            return Boolean.TRUE;
        });
        // 返回
        return inspectionPlan.getId();
    }

    @Override
    public void updateInspectionPlan(InspectionPlanUpdateReqVO updateReqVO) {
        // 校验存在
        validateInspectionPlanExists(updateReqVO.getId());
        // 若存在有效巡检任务需删除后进行更新
        InspectionPlanJobExportReqVO exportReqVO = new InspectionPlanJobExportReqVO();
        exportReqVO.setPlanId(updateReqVO.getId());
        exportReqVO.setStatus(CommonStatusEnum.ENABLE.getCode());
        List<InspectionPlanJobDO> planJobList = inspectionPlanJobService.getInspectionPlanJobList(exportReqVO);
        if (CollectionUtil.isNotEmpty(planJobList)) {
            throw exception(AVALID_INSPECTION_UPDATE_TASK);
        }
        InspectionPlanDO inspectionPlanDO = inspectionPlanMapper.selectById(updateReqVO.getId());
        InspectionPlanDO updateObj = InspectionPlanConvert.INSTANCE.convert(updateReqVO);
        transactionTemplate.execute(status -> {
            inspectionPlanMapper.updateById(updateObj);
            inspectionPlanDeviceService.createPlanDevice(updateReqVO.getId(),updateReqVO.getDeviceList());
            return Boolean.TRUE;
        });
        // 开始日期、结束日期、计划周期发生变动的话，发送消息通知计划人
        if (!inspectionPlanDO.getStartDate().equals(updateObj.getStartDate()) ||
                !inspectionPlanDO.getEndDate().equals(updateObj.getEndDate()) ||
                !inspectionPlanDO.getCycle().equals(updateObj.getCycle())){
            //TODO 若已经创建了任务，进行消息提醒
            String message = "";
            saveMessageInfo(message, updateObj.getUserId());
        }
    }

    @Override
    public void deleteInspectionPlan(Long id) {
        // 校验存在
        validateInspectionPlanExists(id);
        // 若存在有效巡检任务需删除后进行删除
        InspectionPlanJobExportReqVO exportReqVO = new InspectionPlanJobExportReqVO();
        exportReqVO.setPlanId(id);
        exportReqVO.setStatus(CommonStatusEnum.ENABLE.getCode());
        List<InspectionPlanJobDO> planJobList = inspectionPlanJobService.getInspectionPlanJobList(exportReqVO);
        if (CollectionUtil.isNotEmpty(planJobList)) {
            throw exception(AVALID_INSPECTION_DELETE_TASK);
        }
        transactionTemplate.execute(status -> {
            inspectionPlanMapper.deleteById(id);
            inspectionPlanDeviceService.deleteByPlanId(id);
            return Boolean.TRUE;
        });
    }

    private void validateInspectionPlanExists(Long id) {
        if (inspectionPlanMapper.selectById(id) == null) {
            throw exception(INSPECTION_PLAN_NOT_EXISTS);
        }
    }

    @Override
    public InspectionPlanDO getInspectionPlan(Long id) {
        return inspectionPlanMapper.selectById(id);
    }

    @Override
    public List<InspectionPlanDO> getInspectionPlanList(Collection<Long> ids) {
        return inspectionPlanMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<InspectionPlanDO> getInspectionPlanPage(InspectionPlanPageReqVO pageReqVO) {
        return inspectionPlanMapper.selectPage(pageReqVO);
    }

    @Override
    public List<InspectionPlanDO> getInspectionPlanList(InspectionPlanExportReqVO exportReqVO) {
        return inspectionPlanMapper.selectList(exportReqVO);
    }

    @Override
    public PageResult<InspectionPlanDO> getInspectionPlanAppPage(InspectionPlanPageReqVO pageReqVO) {
        return inspectionPlanMapper.selectAppPage(pageReqVO);
    }

    public void saveMessageInfo(String message,Long targetUserId) {
        InspectionPlanMessageCreateReqVO vo = new InspectionPlanMessageCreateReqVO();
        vo.setMessage(message);
        vo.setTargetUserId(targetUserId);
        vo.setStatus(MessageStatusEnum.NOT_SEND.getCode());
        inspectionPlanMessageService.createInspectionPlanMessage(vo);
    }

}
